﻿#ifndef CONDUCTEDTESTFLOWSESSION_H
#define CONDUCTEDTESTFLOWSESSION_H
#include "itestflow.h"
#include <QThread>
#include "3rdparty/includes/signalgenerators/signalgenerator/isignalgenerator.h"
#include "3rdparty/includes/poweramplifiers/poweramplifier/ipoweramplifier.h"
#include "3rdparty/includes/powermeters/powermeter/ipowermeter.h"
#include "3rdparty/includes/switchunits/switchunit/iswitchunit.h"
#include "3rdparty/includes/receivers/receiver/ireceiver.h"
#include "model/deviceinstancemanager.h"
#include "3rdparty/includes/deviceio/ideviceio.h"

/**
 * CS114逻辑整理
 * 1.环境电平扫描：
 *  --使用监测探头夹在被测件（电缆）上，使用接收机扫描频率范围内的环境场强数据，添加安全裕度后，生成限值表。
 * 2.校准：
 *  --使用信号源+功放向校准件注入信号，使用接收机接入监测口，监测信号强度，使其达到目标频率下的限值，记录正向功率，监测功率，信号源幅度等数据。
 * 3.测试：
 *  --使用将监测探头和注入探头同时夹在实测件（电缆）上，使用信号源 + 功放向注入探头注入干扰信号。
 *  --闭环法：使监测功率达到指定频率限值。
 *      --如果选择了校准表：功率调整后检查是否达到校准表中的正常功率值，如果达到则测试通过。
 *      --如果添加了功率容限：将当前限值表或固定限值曲线向上平移指定dB单位，生成新的容限曲线，将容限曲线作为目标极限值进行测试。
 *      --如果同时选择校准表和功率容限，只需其中有一项达到目标值，将视为测试通过。
 *      (为保证测试安全性，使下一次调整不超过目标限值且不超过校准正向功率，使用两者中的较小值)
 *  --替代法：区分前向功率标定和发生器电平。
 *      --前向功率标定：以校准表中的前向功率作为目标值进行测试。
 *      --发生器电平：以监测端功率作为目标值进行测试。
 */

struct ConductedTestFlowSession : public TestFlowSession {
    DeviceHandle<IDeviceIO> generatorIO;
    DeviceHandle<IDeviceIO> amplifierIO;
    DeviceHandle<IDeviceIO> forwardPowerMeterIO;
    DeviceHandle<IDeviceIO> reversePowerMeterIO;
    DeviceHandle<IDeviceIO> monitorPowerMeterIO;
    DeviceHandle<IDeviceIO> receiverIO;
    DeviceHandle<IDeviceIO> switchUnitIO;

    DeviceHandle<ISignalGenerator> generator;
    DeviceHandle<IPowerAmplifier> amplifier;
    DeviceHandle<IPowerMeter> forwardPowerMeter;
    DeviceHandle<IPowerMeter> reversePowerMeter;
    DeviceHandle<IPowerMeter> monitorPowerMeter;
    DeviceHandle<IReceiver> receiver;
    DeviceHandle<ISwitchUnit> switchUnit;
    int fwdPowerMeterChannel = 1;
    int revPowerMeterChannel = 1;
    int monPowerMeterChannel = 1;

    bool rfMuted = true; //设置静默
    void safeMuteAllOutputs() override;
    bool ensureOutputsEnabled() override;
    bool initReceiver(const QString &mode = "N9038A");
    bool setAmplifierOutput(bool st);
    bool setGeneratorOutput(bool st);

    bool setFrequency(double freq, const TestFlowCallbacks &callbacks);
    bool setInputLevel(double level, const TestFlowCallbacks &callbacks);

    double readFwdPower(const QString &arg = "");
    double readRevPower(const QString &arg = "");
    double readMonitorPower(const QString &arg = "", double impedance = 50);

    void closeAll() override;
};

class ConductedFlow : public ITestFlow
{
public:
    QString name() const override { return "Conducted"; }

    bool ensureSessionsForSubrange(const Exec::Subrange &subrange,
                                   TestFlowSessionPtr reuseCandidate,
                                   TestFlowSessionPtr &outSession,
                                   TestFlowCallbacks callbacks,
                                   QString &errorMessage) override;

    void safeMuteAllOutputs(const TestFlowSessionPtr &session) override;

    bool measureOnePoint(const Exec::Subrange &subrange,
                         int frequencyIndex,
                         const TestFlowSessionPtr &session,
                         TestFlowCallbacks callbacks,
                         QString &errorMessage) override;
    void setPlanOptions(const FlowPlanOptions &opts) override;

private:
    bool checkConfigurationValidity(const Exec::Subrange &subrange, QString &errorMessage);
    int adjust(double &currentInputVal, double currentVal, double targetVal, double precisionGradeUp, double precisionGradeDown, double levelMin, double levelMax, double inputMax, QString &errorMessage);

private:
    FlowPlanOptions options_; // 保存计划级参数
    double preInputVal = -95;
};

#endif // CONDUCTEDTESTFLOWSESSION_H
